#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>
#include <unistd.h>
#include <time.h>

#define BUFFER_SIZE 1024
#define PORT 0

// 计算校验和
unsigned short checksum(unsigned short *buf, int size) {
    unsigned long cksum = 0;
    while (size > 1) {
        cksum += *buf++;
        size -= sizeof(unsigned short);
    }
    if (size) {
        cksum += *(unsigned char *)buf;
    }
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >> 16);
    return (unsigned short)(~cksum);
}

int main() {
    int sockfd;
    struct sockaddr_in servaddr, cliaddr;
    socklen_t len;
    char buffer[BUFFER_SIZE];

    if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
        perror("socket creation failed");
        return -1;
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = INADDR_ANY;
    servaddr.sin_port = htons(PORT);

    while (1) {
        len = sizeof(cliaddr);

        int n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&cliaddr, &len);
        if (n < 0) {
            perror("recvfrom");
            continue;
        }

        struct icmphdr *icmp_hdr = (struct icmphdr *)(buffer + sizeof(struct iphdr));
        if (icmp_hdr->type == ICMP_ECHO) {

            time_t current_time = time(NULL);
            struct tm *tm_info = localtime(&current_time);
            char time_str[26];
            strftime(time_str, 26, "%Y-%m-%d %H:%M:%S", tm_info);

            icmp_hdr->type = ICMP_ECHOREPLY;
            icmp_hdr->checksum = 0;
            memcpy(buffer + sizeof(struct iphdr) + sizeof(struct icmphdr), time_str, strlen(time_str));
            icmp_hdr->checksum = checksum((unsigned short *)(buffer + sizeof(struct iphdr)), n - sizeof(struct iphdr));

            if (sendto(sockfd, buffer, n, 0, (struct sockaddr *)&cliaddr, len) < 0) {
                perror("sendto");
            }
        }
    }

    close(sockfd);
    return 0;
}
    